import { Context } from "./Context";
import { SRMIReturn } from "./SRMIReturn";
import { SerializeStream } from "../../Framework/Serialize/SerializeStream";
import { ERMIMessageType } from "./ERMIMessageType";
import { SRMICall } from "./SRMICall";
import { RMIObject } from "./RMIObject";
import { RMIDispatcher } from "./RMIDispatcher";
import { RMIEvent } from "./RMIEvent";
import { Exception } from "../../Framework/Util/Exception";
import { RMIException } from "./RMIException";
import { RMIObjectBind } from "./RMIObjectBind";
import { ERMICallModel } from "./ERMICallModel";
//class Outgoing

export class Outgoing {
  public static dispatch(
    arg1: Context,
    arg2: SRMIReturn,
    arg3: SerializeStream
  ): Boolean {
    if (!arg1._connection) {
      return false;
    }
    var stream = new SerializeStream();
    ERMIMessageType.MessageTypeCallRet.__write(stream);
    arg2.__write(stream);
    stream.writeByteArray(arg3);
    return !(arg1._connection.send(stream.byteArray) == -1);
  }

  public static invokeAsync(
    context: Context,
    arg2: SRMICall,
    stream: SerializeStream,
    rmiObject: RMIObject
  ): void {
    if (
      RMIDispatcher.getInstance().hasEventListener(RMIEvent.CALL_INTERFACE_TYPE)
    ) {
      RMIDispatcher.getInstance().dispatchEvent(
        new RMIEvent(
          RMIEvent.CALL_INTERFACE_TYPE,
          false,
          false,
          null,
          rmiObject.toString()
        )
      );
    }
    if (context._session.communicator == null) {
      var loc2 = new Exception(
        "ExceptionCodeNotInstantiation",
        RMIException.ExceptionCodeNotInstantiation
      );
      rmiObject.cdeException(loc2);
      return;
    }
    var prepareCommandHandler =
      context._session.communicator.prepareCommandHandler;
    if (null != prepareCommandHandler) {
      if (!prepareCommandHandler.prepareCommand(arg2, context, rmiObject)) {
        return;
      }
    }
    if (null != rmiObject) {
      Outgoing.invokeAsyncBack(context, arg2, stream, rmiObject);
    } else {
      Outgoing.invokeAsyncNoBack(context, arg2, stream);
    }
    return;
  }

  private static invokeAsyncBack(
    context: Context,
    arg2: SRMICall,
    arg3: SerializeStream,
    arg4: RMIObject
  ): void {
    var rmiObjectBind = new RMIObjectBind();
    arg4.identity = arg2.identity;
    rmiObjectBind.messageId = context._session.addBackObject(
      rmiObjectBind,
      context._timeOut
    );
    rmiObjectBind.rmiObject = arg4;
    rmiObjectBind.outgoingStatus = RMIObjectBind.EOutGoingWaitToSend;
    rmiObjectBind.session = context._session;
    var loc3 = new SerializeStream();
    ERMIMessageType.MessageTypeCall.__write(loc3);
    arg2.callSynchType = ERMICallModel.CallModelAsync;
    arg2.messageId = rmiObjectBind.messageId;
    if (arg2.messageId <= 0) {
      let rimiException = new Exception(
        "Outgoing:: context._session.addBackObject exception",
        Exception.ExceptionCodeBase
      );
      arg4.cdeException(rimiException);
    }
    arg2.__write(loc3);
    loc3.writeByteArray(arg3);
    if (context._connection == null) {
      context._connection = context._session.connection;
    }
    rmiObjectBind.buffer = loc3;
    if (context._connection != null) {
      if (-1 == context._connection.send(loc3.byteArray)) {
        context._session.findRemoveBackObject(arg2.messageId);
        let rimiException = new RMIException(
          "Outgoing:: context._connection.send exception",
          RMIException.ExceptionCodeConnectionWrite
        );
        arg4.cdeException(rimiException);
      }
    } else if (
      context._session.communicator &&
      !context._session.communicator.connecting
    ) {
      if (context._session.communicator.connect()) {
        context._session.addMessage(rmiObjectBind);
        return;
      }
    } else {
      context._session.addMessage(rmiObjectBind);
    }
    return;
  }

  public static invokeAsyncNoBack(
    arg1: Context,
    arg2: SRMICall | null,
    arg3: SerializeStream
  ): void {
    var rmiObjectBind = new RMIObjectBind();
    rmiObjectBind.messageId = 0;
    // @ts-ignore
    rmiObjectBind.rmiObject = null;
    rmiObjectBind.outgoingStatus = RMIObjectBind.EOutGoingWaitToSend;
    var loc2 = new SerializeStream();
    if (
      arg1._messageType &&
      arg1._messageType.equals(ERMIMessageType.MessageTypeMQ)
    ) {
      arg1._messageType.__write(loc2);
    } else {
      ERMIMessageType.MessageTypeCall.__write(loc2);
      arg2!.messageId = 0;
      arg2!.callSynchType = ERMICallModel.CallModelAsync;
      arg2!.__write(loc2);
    }
    loc2.writeByteArray(arg3);
    if (arg1._connection == null) {
      arg1._connection = arg1._session.connection;
    }
    if (arg1._connection != null) {
      arg1._connection.send(loc2.byteArray);
    } else if (!arg1._session.communicator.connecting) {
      if (arg1._session.communicator.connect()) {
        rmiObjectBind.buffer = loc2;
        arg1._session.addMessage(rmiObjectBind);
        return;
      }
    }
  }
}
